package com.lineage.server.datatables.sql;

import com.lineage.DatabaseFactory;
import com.lineage.server.IdFactory;
import com.lineage.server.datatables.storage.ClanStorage;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.model.L1Clan;
import com.lineage.server.utils.PerformanceTimer;
import com.lineage.server.utils.SQLUtil;
import com.lineage.server.world.WorldClan;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ClanTable implements ClanStorage {
  private static final Log _log = LogFactory.getLog(ClanTable.class);
  
  private final Map<Integer, L1Clan> _clans = new HashMap<>();
  
  private static ClanTable _instance;
  
  public static ClanTable getInstance() {
    if (_instance == null)
      _instance = new ClanTable(); 
    return _instance;
  }
  
  public void load() {
    PerformanceTimer timer = new PerformanceTimer();
    Connection cn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {
      cn = DatabaseFactory.get().getConnection();
      ps = cn.prepareStatement("SELECT * FROM `clan_data` ORDER BY `clan_id`");
      rs = ps.executeQuery();
      while (rs.next()) {
        L1Clan clan = new L1Clan();
        int clan_id = rs.getInt("clan_id");
        clan.setClanId(clan_id);
        clan.setClanName(rs.getString("clan_name"));
        clan.setLeaderId(rs.getInt("leader_id"));
        clan.setLeaderName(rs.getString("leader_name"));
        clan.setCastleId(rs.getInt("hascastle"));
        clan.setHouseId(rs.getInt("hashouse"));
        clan.setFoundDate(rs.getTimestamp("found_date"));
        clan.setAnnouncement(rs.getString("announcement"));
        clan.setEmblemId(rs.getInt("emblem_id"));
        clan.setEmblemStatus(rs.getInt("emblem_status"));
        clan.setClanLevel(rs.getInt("clan_level"));
        clan.setClanContribution(rs.getInt("clan_contribution"));
        clan.setClanSkillId(rs.getInt("clanskill_id"));
        clan.setClanSkillLv(rs.getInt("clanskill_lv"));
        clan.setclanadena(rs.getInt("clan_adena"));
        boolean clanskill = rs.getBoolean("clanskill");
        if (clanskill) {
          clan.set_clanskill(clanskill);
          Timestamp skilltime = rs.getTimestamp("skilltime");
          clan.set_skilltime(skilltime);
        } 
        WorldClan.get().storeClan(clan);
        this._clans.put(Integer.valueOf(clan_id), clan);
      } 
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(rs);
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
    _log.info("载入血盟资料资料数量: " + this._clans.size() + "(" + timer.get() + "ms)");
    Collection<L1Clan> AllClan = WorldClan.get().getAllClans();
    Iterator<L1Clan> iterator = AllClan.iterator();
    while (iterator.hasNext()) {
      L1Clan clan2 = iterator.next();
      Connection cn2 = null;
      PreparedStatement ps2 = null;
      ResultSet rs2 = null;
      try {
        cn2 = DatabaseFactory.get().getConnection();
        ps2 = cn2.prepareStatement("SELECT `char_name` FROM `characters` WHERE `ClanID`=?");
        ps2.setInt(1, clan2.getClanId());
        rs2 = ps2.executeQuery();
        while (rs2.next())
          clan2.addMemberName(rs2.getString("char_name")); 
      } catch (SQLException e2) {
        _log.error(e2.getLocalizedMessage(), e2);
        continue;
      } finally {
        SQLUtil.close(rs2);
        SQLUtil.close(ps2);
        SQLUtil.close(cn2);
      } 
    } 
    Iterator<L1Clan> iterator2 = AllClan.iterator();
    while (iterator2.hasNext()) {
      L1Clan clan2 = iterator2.next();
      clan2.getDwarfForClanInventory().loadItems();
    } 
  }
  
  public void addDeClan(Integer integer, L1Clan l1Clan) {
    WorldClan.get().storeClan(l1Clan);
    this._clans.put(integer, l1Clan);
  }
  
  public L1Clan createClan(L1PcInstance player, String clan_name) {
    Collection<L1Clan> allClans = WorldClan.get().getAllClans();
    Iterator<L1Clan> iter = allClans.iterator();
    while (iter.hasNext()) {
      L1Clan oldClans = iter.next();
      if (oldClans.getClanName().equalsIgnoreCase(clan_name))
        return null; 
    } 
    L1Clan clan = new L1Clan();
    clan.setClanId(IdFactory.get().nextId());
    clan.setClanName(clan_name);
    clan.setLeaderId(player.getId());
    clan.setLeaderName(player.getName());
    clan.setCastleId(0);
    clan.setHouseId(0);
    clan.setFoundDate(new Timestamp(System.currentTimeMillis()));
    clan.setAnnouncement("");
    clan.setEmblemId(0);
    clan.setEmblemStatus(0);
    clan.setClanLevel(0);
    clan.setClanContribution(0);
    clan.set_clanskill(false);
    Connection cn = null;
    PreparedStatement ps = null;
    try {
      cn = DatabaseFactory.get().getConnection();
      ps = cn.prepareStatement(
          "INSERT INTO `clan_data` SET `clan_id`=?,`clan_name`=?,`leader_id`=?,`leader_name`=?,`hascastle`=?,`hashouse`=?, found_date=?, announcement=?, emblem_id=?, emblem_status=?,`clan_level`=?,`clan_contribution`=?,`clanskill`=?,`skilltime`=?,`clan_adena`=?");
      int i = 0;
      ps.setInt(++i, clan.getClanId());
      ps.setString(++i, clan.getClanName());
      ps.setInt(++i, clan.getLeaderId());
      ps.setString(++i, clan.getLeaderName());
      ps.setInt(++i, clan.getCastleId());
      ps.setInt(++i, clan.getHouseId());
      ps.setTimestamp(++i, new Timestamp(System.currentTimeMillis()));
      ps.setString(++i, "");
      ps.setInt(++i, 0);
      ps.setInt(++i, 0);
      ps.setInt(++i, clan.getClanLevel());
      ps.setInt(++i, clan.getClanContribution());
      ps.setBoolean(++i, clan.isClanskill());
      ps.setTimestamp(++i, clan.get_skilltime());
      ps.setInt(++i, clan.getclanadena());
      ps.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
    WorldClan.get().storeClan(clan);
    this._clans.put(Integer.valueOf(clan.getClanId()), clan);
    player.setClanid(clan.getClanId());
    player.setClanname(clan.getClanName());
    player.setClanRank(10);
    clan.addMemberName(player.getName());
    try {
      player.save();
    } catch (Exception e2) {
      _log.error(e2.getLocalizedMessage(), e2);
    } 
    return clan;
  }
  
  public void updateClan(L1Clan clan) {
    Connection cn = null;
    PreparedStatement ps = null;
    try {
      cn = DatabaseFactory.get().getConnection();
      ps = cn.prepareStatement(
          "UPDATE clan_data SET `clan_id`=?,`leader_id`=?,`leader_name`=?,`hascastle`=?,`hashouse`=?, found_date=?, announcement=?, emblem_id=?, emblem_status=?,`clan_level`=?,`clan_contribution`=?,`clanskill`=?,`skilltime`=?,`clan_adena`=? WHERE `clan_name`=?");
      int i = 0;
      ps.setInt(++i, clan.getClanId());
      ps.setInt(++i, clan.getLeaderId());
      ps.setString(++i, clan.getLeaderName());
      ps.setInt(++i, clan.getCastleId());
      ps.setInt(++i, clan.getHouseId());
      ps.setTimestamp(++i, clan.getFoundDate());
      ps.setString(++i, clan.getAnnouncement());
      ps.setInt(++i, clan.getEmblemId());
      ps.setInt(++i, clan.getEmblemStatus());
      ps.setInt(++i, clan.getClanLevel());
      ps.setInt(++i, clan.getClanContribution());
      ps.setBoolean(++i, clan.isClanskill());
      ps.setTimestamp(++i, clan.get_skilltime());
      ps.setInt(++i, clan.getclanadena());
      ps.setString(++i, clan.getClanName());
      ps.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
  }
  
  public void deleteClan(String clan_name) {
    L1Clan clan = WorldClan.get().getClan(clan_name);
    if (clan == null)
      return; 
    Connection cn = null;
    PreparedStatement ps = null;
    try {
      cn = DatabaseFactory.get().getConnection();
      ps = cn.prepareStatement("DELETE FROM `clan_data` WHERE `clan_name`=?");
      ps.setString(1, clan_name);
      ps.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
    clan.getDwarfForClanInventory().clearItems();
    clan.getDwarfForClanInventory().deleteAllItems();
    WorldClan.get().removeClan(clan);
    this._clans.remove(Integer.valueOf(clan.getClanId()));
  }
  
  public L1Clan getTemplate(int clan_id) {
    return this._clans.get(Integer.valueOf(clan_id));
  }
  
  public Map<Integer, L1Clan> get_clans() {
    return this._clans;
  }
  
  public void updateClanSkill(L1Clan clan) {
    Connection cn = null;
    PreparedStatement ps = null;
    try {
      cn = DatabaseFactory.get().getConnection();
      ps = cn.prepareStatement("UPDATE clan_data SET `clanskill_id`=?,`clanskill_lv`=? WHERE `clan_id`=?");
      ps.setInt(1, clan.getClanSkillId());
      ps.setInt(2, clan.getClanSkillLv());
      ps.setInt(3, clan.getClanId());
      ps.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
  }
}
